package org.example.c_0_005;

import org.junit.Test;

import java.util.ArrayList;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 定义一个容器类
 * 实现一个队列，最大容量为10。有2个生产者，10个消费者。要保证程序正常执行且队列大小不会溢出。
 * synchronized 实现较为简单
 * 示例： ReentrantLock
 */
public class T_Topic02<T> {
    private ArrayList<T> list;
    private volatile int count = 0;
    private final int MAX = 10;
    private ReentrantLock lock = new ReentrantLock();
    private Condition produce = lock.newCondition();
    private Condition consumer = lock.newCondition();

    public T_Topic02() {
        this.list = new ArrayList<T>();
    }

    public void put(T t){
        try {
            lock.lock();
            while (count==MAX){
                produce.await();
            }
            list.add(t);
            count++;
            consumer.signalAll();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }finally {
            System.out.println("添加："+ t + "大小：" + count);
            lock.unlock();
        }
    }

    public T get(){
        T t = null;
        try {
            lock.lock();
            while(count==0){
                consumer.await();
            }
            t = list.remove(0);
            count--;
            produce.signalAll();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }finally {
            System.out.println("删除：" + t + "大小：" + count);
            lock.unlock();
        }
        return t;
    }

    public static void main(String[] args) throws InterruptedException {
        T_Topic02<Integer> container = new T_Topic02<>();
        for (int i = 0; i < 2; i++) {
            new Thread(()->{
                for (int j = 0; j < 10; j++) {
                    container.put(j);
                }
            }).start();
        }

        for (int i = 0; i < 5; i++) {
            new Thread(()->{
                for (int j = 0; j < 4; j++) {
                    container.get();
                }
            }).start();
        }

        Thread.sleep(5000);
    }

}
